
from typing import Callable, Optional



class sCc9dPkg:
    from_port: int  # 源端口号，发送方的端口号
    to_port: int  # 目的端口号，接收方的端口号
    remote_addr: int  # 远端地址，对于收到的包，是发送方地址，对于要发送的包，是接收方地址
    datas: Optional[bytes] = None  # 数据部分，最大64字节，默认值为None
    _dir: str = "s"  # 方向，"s"表示发送，"r"表示接收

    def __init__(self, from_port: int = 0, to_port: int = 0, remote_addr: int = 0, datas:bytes = None ) -> None:  
        self.from_port = from_port
        self.to_port = to_port
        self.remote_addr = remote_addr
        self.datas = datas

    def asRecv(self) -> None:
        self._dir = "r"
    
    def asSend(self) -> None:
        self._dir = "s"

    def __repr__(self) -> str:
        data_str = ' '.join(f'{byte:02x}' for byte in self.datas)
        if self._dir == "s":
            return f"this.{self.from_port}->{self.remote_addr:04x}.{self.to_port}: {data_str}"
        elif self._dir == "r":
            return f"{self.remote_addr:04x}.{self.from_port}->this.{self.to_port}: {data_str}"
        else:
            return f"remote_addr={self.remote_addr:04x},{self.from_port}->{self.to_port}: {data_str}"  


class CC9DProtocolParser:    
    MAC_SIZE = 5  # from_port (1 byte) + to_port (1 byte) + remote_addr (2 bytes) + end_crc (1 byte)
    MAX_DATA_SIZE = 64
    SEPARATOR = 0x9d
    ESCAPE = 0x9e
    ESC_9D = 0xfe
    ESC_9E = 0xff

    def _printd(self, *args, **kwargs):
        if self._do_print:
            print(*args, **kwargs)

    _Crc_table = bytes([        
        0x00,0x31,0x62,0x53,0xc4,0xf5,0xa6,0x97,0xb9,0x88,0xdb,0xea,0x7d,0x4c,0x1f,0x2e,
        0x43,0x72,0x21,0x10,0x87,0xb6,0xe5,0xd4,0xfa,0xcb,0x98,0xa9,0x3e,0x0f,0x5c,0x6d,
        0x86,0xb7,0xe4,0xd5,0x42,0x73,0x20,0x11,0x3f,0x0e,0x5d,0x6c,0xfb,0xca,0x99,0xa8,
        0xc5,0xf4,0xa7,0x96,0x01,0x30,0x63,0x52,0x7c,0x4d,0x1e,0x2f,0xb8,0x89,0xda,0xeb,
        0x3d,0x0c,0x5f,0x6e,0xf9,0xc8,0x9b,0xaa,0x84,0xb5,0xe6,0xd7,0x40,0x71,0x22,0x13,
        0x7e,0x4f,0x1c,0x2d,0xba,0x8b,0xd8,0xe9,0xc7,0xf6,0xa5,0x94,0x03,0x32,0x61,0x50,
        0xbb,0x8a,0xd9,0xe8,0x7f,0x4e,0x1d,0x2c,0x02,0x33,0x60,0x51,0xc6,0xf7,0xa4,0x95,
        0xf8,0xc9,0x9a,0xab,0x3c,0x0d,0x5e,0x6f,0x41,0x70,0x23,0x12,0x85,0xb4,0xe7,0xd6,
        0x7a,0x4b,0x18,0x29,0xbe,0x8f,0xdc,0xed,0xc3,0xf2,0xa1,0x90,0x07,0x36,0x65,0x54,
        0x39,0x08,0x5b,0x6a,0xfd,0xcc,0x9f,0xae,0x80,0xb1,0xe2,0xd3,0x44,0x75,0x26,0x17,
        0xfc,0xcd,0x9e,0xaf,0x38,0x09,0x5a,0x6b,0x45,0x74,0x27,0x16,0x81,0xb0,0xe3,0xd2,
        0xbf,0x8e,0xdd,0xec,0x7b,0x4a,0x19,0x28,0x06,0x37,0x64,0x55,0xc2,0xf3,0xa0,0x91,
        0x47,0x76,0x25,0x14,0x83,0xb2,0xe1,0xd0,0xfe,0xcf,0x9c,0xad,0x3a,0x0b,0x58,0x69,
        0x04,0x35,0x66,0x57,0xc0,0xf1,0xa2,0x93,0xbd,0x8c,0xdf,0xee,0x79,0x48,0x1b,0x2a,
        0xc1,0xf0,0xa3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1a,0x2b,0xbc,0x8d,0xde,0xef,
        0x82,0xb3,0xe0,0xd1,0x46,0x77,0x24,0x15,0x3b,0x0a,0x59,0x68,0xff,0xce,0x9d,0xac
    ]  ) 
    
    def __init__(self, sendByteCB: Callable[[bytes], bool], recvPkgCB: Callable[[sCc9dPkg], None]):
        # 发送相关程序
        self._sendByteCB = sendByteCB
        self._sendByteCB(bytes([self.SEPARATOR, self.SEPARATOR]))  # 发送起始字节。
        # 下面是接收相关
        self._recv_buffer = bytearray()
        self._recv_in_esc = False
        self._recvPkgCB = recvPkgCB  # 初始化接收回调函数
        if __name__ == "__main__":
            self._do_print = True
            self._printd("CC9D 会输出调试信息")
        else:
            self._do_print = False

        
    
    
    def send(self, pkg: sCc9dPkg) -> None:
        data = self._build(pkg)
        self._sendByteCB(data)
    
    def _build(self, pkg: sCc9dPkg) -> bytes:
        data = bytearray()
        send_crc = 0xff	
        def escape_and_append(byte: int) -> None:
            if byte == self.SEPARATOR:
                data.append(self.ESCAPE)
                data.append(self.ESC_9D)
            elif byte == self.ESCAPE:
                data.append(self.ESCAPE)
                data.append(self.ESC_9E)
            else:
                data.append(byte)

        escape_and_append(pkg.from_port)
        send_crc = self._Crc_table[send_crc ^ pkg.from_port]
        escape_and_append(pkg.to_port)
        send_crc = self._Crc_table[send_crc ^ pkg.to_port]
        escape_and_append(pkg.remote_addr & 0xFF)
        send_crc = self._Crc_table[send_crc ^ (pkg.remote_addr & 0xFF)]
        escape_and_append((pkg.remote_addr >> 8) & 0xFF)
        send_crc = self._Crc_table[send_crc ^ ((pkg.remote_addr >> 8) & 0xFF)]
        if pkg.datas:
            for byte in pkg.datas:
                escape_and_append(byte)
                send_crc = self._Crc_table[send_crc ^ byte]
                pass
            pass
                
        escape_and_append(send_crc)
        data.append(self.SEPARATOR)
        return bytes(data)
    
    def receive(self, data: bytes) -> None:
        for byte in data:
            self._receiveByte(byte)
            
    def _receiveByte(self, byte: int) -> None:
        if self._recv_in_esc:
            self._recv_in_esc = False
            if byte == self.ESC_9D:
                self._recv_buffer.append(self.SEPARATOR)
            elif byte == self.ESC_9E:
                self._recv_buffer.append(self.ESCAPE)
            else:
                self._printd(f"接收到未知的转义字符: {byte}")
        else:
            if byte == self.ESCAPE:
                self._recv_in_esc = True
            elif byte == self.SEPARATOR:
                self._receiveEnd()
            else:
                self._recv_buffer.append(byte)
    def _receiveEnd(self) -> None:
        if len(self._recv_buffer) < self.MAC_SIZE:
            self._printd(f"接收到的数据长度不足: {len(self._recv_buffer)}")
            self._recv_buffer.clear()
            return
        recv_crc = 0xff
        for byte in self._recv_buffer[:-1]:
            recv_crc = self._Crc_table[recv_crc ^ byte]
        if recv_crc != self._recv_buffer[-1]:
            self._printd(f"接收到的数据 CRC 错误: {recv_crc} != {self._recv_buffer[-1]}")
            self._recv_buffer.clear()
            return
        from_port = self._recv_buffer[0]
        to_port = self._recv_buffer[1]
        remote_addr = self._recv_buffer[2] + (self._recv_buffer[3] << 8)
        datas = self._recv_buffer[self.MAC_SIZE-1:-1]
        pkg = sCc9dPkg(from_port=from_port, to_port=to_port, remote_addr=remote_addr)
        pkg.datas = datas
        pkg.asRecv()
        self._recvPkgCB(pkg)  # 调用接收回调函数
        self._recv_buffer.clear()
        return   

if __name__ == "__main__":
    print("***  CC9DProtocolParser 测试  ***")
    def sendByteCB(data: bytes) -> bool:
        hex_output = ' '.join(f'{byte:02x}' for byte in data)
        print(f"接收到的数据 (16进制): {hex_output}")
        return True
    
    def recvPkgCB(pkg: sCc9dPkg) -> None:
        print(f"接收到的数据包: from_port={pkg.from_port}, to_port={pkg.to_port}, remote_addr={pkg.remote_addr}, datas={pkg.datas}")

    # 创建一个 CC9DProtocolParser 实例
    parser = CC9DProtocolParser(sendByteCB,recvPkgCB)

    # 创建一个 sCc9dPkg 实例
    pkg = sCc9dPkg(
        from_port=0x01,
        to_port=0x02,
        remote_addr=0x1234,
        datas=bytes([0x10, 0x20, 0x30, 0x40])
    )
    # 调用 send 方法发送数据
    parser.send(pkg)
    # 调用 receive 方法接收数据
    parser.receive(b'\x9d\x9d\x01\x02\x34\x12\x10\x20\x30\x40\xe7\x9d')
